package backend;

import java.beans.XMLEncoder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 *
 * @author Khazidhea
 */
public class Core {

    private ArrayList<Server> serverList;
    private ArrayList<Plugin> eventList;

    public Core() {
        eventList = new ArrayList<Plugin>();
        //Load everything from file
        readEventList();
        readSeverList();
    }

    /**
     * Reads event list from file
     * @param fileName
     */
    public void readEventList(String fileName) {
        try {
            File file = new File(fileName);
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();
            //System.out.println("Root element " + doc.getDocumentElement().getNodeName());
            NodeList nodeLst = doc.getElementsByTagName("event");
            eventList = new ArrayList<Plugin>();
            for (int i = 0; i < nodeLst.getLength(); ++i) {
                Node fstNode = nodeLst.item(i);
                if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element fstElmnt = (Element) fstNode;

                    String name = fstElmnt.getAttribute("name");
                    String type = fstElmnt.getAttribute("type");
                    String command = fstElmnt.getAttribute("command");
                    //System.out.println("Name : "  + name);
                    //System.out.println("Type : "  + type);
                    //System.out.println("Command : "  + command);

                    ArrayList<Server> servers = new ArrayList<Server>();
                    NodeList serverElementList = fstElmnt.getElementsByTagName("server");
                    for (int j = 0; j < serverElementList.getLength(); ++j) {

                        Element serverElement = (Element) serverElementList.item(j);
                        String serverName = serverElement.getAttribute("name");
                        String serverIp = serverElement.getAttribute("ip");
                        //System.out.println("serverName: " + serverName);
                        //System.out.println("serverIp: " + serverIp);

                        ArrayList<String> logs = new ArrayList<String>();
                        NodeList logElementList = serverElement.getElementsByTagName("log");
                        for (int k = 0; k < logElementList.getLength(); ++k) {
                            Element logElement = (Element) logElementList.item(k);
                            String log = logElement.getAttribute("name");
                            //System.out.println("Log : "  + log);
                            logs.add(log);
                        }

                        Server server = new Server(serverName, serverIp, logs);
                        servers.add(server);
                    }



                    eventList.add(new RegexPlugin(name, servers, command));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Reads event list from default file "eventlist.xml"
     */
    public void readEventList() {
        readEventList("eventlist.xml");
    }

    /**
     * Writes event list to file
     * @param fileName
     */
    public void saveEventList(String fileName) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.newDocument();
            Element root = doc.createElement("eventlist");
            for (Plugin eevent : getEventList()) {
                RegexPlugin event = (RegexPlugin) eevent;
                Element eventElement = doc.createElement("event");
                eventElement.setAttribute("name", event.getName());
                eventElement.setAttribute("type", "simple");
                eventElement.setAttribute("command", event.getRegex());
                for (Server server : event.getServerList()) {
                    Element serverElement = doc.createElement("server");
                    serverElement.setAttribute("name", server.getName());
                    serverElement.setAttribute("ip", server.getIp());
                    for (String log : server.getLogs()) {
                        Element logElement = doc.createElement("log");
                        logElement.setAttribute("name", log);
                        serverElement.appendChild(logElement);
                    }
                    eventElement.appendChild(serverElement);
                }
                root.appendChild(eventElement);
            }
            doc.appendChild(root);

            File file = new File(fileName);
            PrintWriter out = new PrintWriter(file);
            DOMSource domSource = new DOMSource(doc);
            StreamResult streamResult = new StreamResult(out);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.transform(domSource, streamResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Write event list to default file "eventlist.xml"
     */
    public void saveEventList() {
        saveEventList("eventlist.xml");
    }

    /**
     * Reads server list from file
     * @param fileName
     */
    public void readSeverList(String fileName) {
        try {
            File file = new File(fileName);
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();
            //System.out.println("Root element " + doc.getDocumentElement().getNodeName());
            NodeList nodeLst = doc.getElementsByTagName("server");
            serverList = new ArrayList<Server>();
            for (int i = 0; i < nodeLst.getLength(); ++i) {
                Node fstNode = nodeLst.item(i);
                if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element fstElmnt = (Element) fstNode;

                    String name = fstElmnt.getAttribute("name");
                    String ip = fstElmnt.getAttribute("ip");
                    //System.out.println("Name : "  + name);
                    //System.out.println("IP : "  + ip);

                    ArrayList<String> logs = new ArrayList<String>();
                    NodeList logElementList = fstElmnt.getElementsByTagName("log");
                    for (int j = 0; j < logElementList.getLength(); ++j) {
                        Element logElement = (Element) logElementList.item(j);
                        String log = logElement.getAttribute("name");
                        //System.out.println("Log : "  + log);
                        logs.add(log);
                    }

                    serverList.add(new Server(name, ip, logs));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Read server list from default file "serverlist.xml"
     */
    public void readSeverList() {
        readSeverList("serverlist.xml");
    }

    /**
     * Writes server list to file
     * @param fileName
     */
    public void saveServerList(String fileName) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.newDocument();
            Element root = doc.createElement("serverlist");
            for (Server server : serverList) {
                Element serverElement = doc.createElement("server");
                serverElement.setAttribute("name", server.getName());
                serverElement.setAttribute("ip", server.getIp());
                for (String log : server.getLogs()) {
                    Element logElement = doc.createElement("log");
                    logElement.setAttribute("name", log);
                    serverElement.appendChild(logElement);
                }
                root.appendChild(serverElement);
            }
            doc.appendChild(root);

            File file = new File(fileName);
            PrintWriter out = new PrintWriter(file);
            DOMSource domSource = new DOMSource(doc);
            StreamResult streamResult = new StreamResult(out);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.transform(domSource, streamResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Writes server list to default file "serverlist.xml"
     */
    public void saveServerList() {
        saveServerList("serverlist.xml");
    }

    /**
     * Adds a new event
     * @param event
     */
    public void addEvent(Plugin event) {
        getEventList().add(event);
    }

    /**
     * Runs event specified
     * @param id
     * @return
     */
    public String runEvent(int id) {
        Plugin event = getEventList().get(id);
        event.check();
        System.out.println(event.getOutput());
        return event.getOutput();
    }

    /**
     * Adds a new server
     * @param server
     */
    public void addServer(Server server) {
        serverList.add(server);
    }

    /**
     * Returns the server list as an ArrayList of Strings
     * @return
     */
    public ArrayList<String> getServers() {
        ArrayList<String> result = new ArrayList<String>();
        for (Server server : serverList) {
            result.add(server.getName() + " - " + server.getIp());
        }
        return result;
    }

    /**
     * Returns the event list as an ArrayList of Strings
     * @return
     */
    public ArrayList<String> getEvents() {
        ArrayList<String> result = new ArrayList<String>();
        for (Plugin event : eventList) {
            result.add(event.getName());
        }
        return result;
    }

    /**
     * Returns the log list of all the servers as an ArrayList of Strings
     * @return
     */
    public ArrayList<String> getLogs() {
        ArrayList<String> result = new ArrayList<String>();
        for (Server server : serverList) {
            for (String log : server.getLogs()) {
                result.add(server.getName() + " - " + log);
            }
        }
        return result;
    }

    /**
     * Returns logs of a specific server
     * @param id
     * @return
     */
    public ArrayList<String> getLogs(int id) {
        Server server = serverList.get(id);
        return server.getLogs();
    }

    /**
     * Returns logs of a specific server
     * @param server
     * @return
     */
    public ArrayList<String> getLogs(Server server) {
        return server.getLogs();
    }

    /**
     * @param serverList the serverList to set
     */
    public void setServerList(ArrayList<Server> serverList) {
        this.serverList = serverList;
    }

    /**
     * @return the serverList
     */
    public ArrayList<Server> getServerList() {
        return serverList;
    }

    /**
     * @return the eventList
     */
    public ArrayList<Plugin> getEventList() {
        return eventList;
    }

    /**
     * @param eventList the eventList to set
     */
    public void setEventList(ArrayList<Plugin> eventList) {
        this.eventList = eventList;
    }
}
